/*
 * FNISVGEditor - JavaScript - based editor for SVG graphics 
 * Copyright (C) 2008 - 2009 Antti Leppä / Foyt
 * http://www.foyt.fi
 * 
 * License: 
 * 
 * Licensed under GNU Lesser General Public License Version 2.1 or later (the "LGPL") 
 * http://www.gnu.org/licenses/lgpl.html
 * 
 * Most of the color conversion algorithms used here are from GIMP's (www.gimp.org) source code. 
 * 
 * To be more specific most of the RGB handling routines are from libgimpcolor/gimprgb.c and 
 * RGB to HSV conversion from libgimpcolor/gimpcolorspace.c 
 */
FNISVGEditorColorRGB = Class.create({
  initialize:function(r,g,b,a) {
    
    this._luminanceRed = 0.2126;
    this._luminanceGreen = 0.7152;
    this._luminanceBlue = 0.0722;
    
    this._intensityRed = 0.30;
    this._intensityGreen = 0.59;
    this._intensityBlue = 0.11;
    
    this._r = r;
    this._g = g;
    this._b = b;
    this._a = a;
  },
  setRGB: function (r, g, b) {
    this._r = r;
    this._g = g;
    this._b = b;
  },
  setAlpha: function (alpha) {
    this._a = alpha;
  },
  getRed: function () {
    return this._r;
  },
  getGreen: function () {
    return this._g;
  },
  getBlue: function () {
    return this._b;
  },
  getAlpha: function () {
    return this._a;
  },
  getMax: function () {
    return Math.max(Math.max(this._r, this._g), this._b);
  },
  getMin: function () {
    return Math.min(Math.min(this._r, this._g), this._b);
  },
  add: function (r, g, b) {
    this._r += r;
    this._g += g;
    this._b += b;
  },
  subtract: function (r, g, b) {
    this._r -= r;
    this._g -= g;
    this._b -= b;
  },
  multiply: function (factor) {
    this._r *= factor;
    this._g *= factor;
    this._b *= factor;
  },
  getDistance: function (r, g, b) {
    return  
      Math.abs(this._r - r) +
      Math.abs(this._g - g) +
      Math.abs(this._b - b);
  },
  clamp: function () {
    this._r = this._clamp(this._r, 0.0, 1.0);
    this._g = this._clamp(this._g, 0.0, 1.0);
    this._b = this._clamp(this._b, 0.0, 1.0);
  },
  getGamma: function (gamma) {
    var g;
    
    if (gamma != 0.0)
      g = 1.0 / gamma;
    else
      g = 0.0;

    this._r = Math.pow(this._r, g);
    this._g = Math.pow(this._g, g);
    this._b = Math.pow(this._b, g);
  },
  getLuminance: function () {
    return this._clamp(this._luminance(this._r, this._g, this._b), 0.0, 1.0);
  },
  getIntensity: function () {
    return this._clamp(this._intensity(this._r, this._g, this._b), 0.0, 1.0);
  },
  invert: function () {
    this._r = 1 - this._r;
    this._g = 1 - this._g;
    this._b = 1 - this._b;
  },
  toHSV: function () {
    var max = this.getMax();
    var min = this.getMin();
    var v = max;
    var s;
    var h;
    var delta = max -min;
    
    if (delta > 0.0001) {
      s = delta / max;
      if (this._r == max) {
        h = (this._g - this._b) / delta;
        if (h < 0.0)
          h += 6.0;
        } else if (this._g == max) {
          h = 2.0 + (this._b - this._r) / delta;
        } else if (this._b == max) {
          h = 4.0 + (this._r - this._g) / delta;
        }

        h /= 6.0;
    } else {
      s = 0.0;
      h = 0.0;
    }
    
    return new FNISVGEditorColorHSV(h, s, v, this._a); 
  },
  toWebColor: function () {
    var result = '#' + [ Math.round(this._r * 255), Math.round(this._g * 255), Math.round(this._b * 255)].invoke('toColorPart').join(''); 
    return result;
  },
  clone: function () {
    return new FNISVGEditorColorRGB(this._r, this._g, this._b, this._a); 
  },
  _clamp: function (x, l, u) {
    return x < l ? l : x > u ? u : x; 
  },
  _luminance: function (r, g, b) {
    return 
      (r * this._luminanceRed) + 
      (g * this._luminanceGreen) + 
      (b * this._luminanceBlue);
  },
  _intensity: function (r, g, b) {
    return 
      (r * this._intensityRed) + 
      (g * this._intensityGreen) + 
      (b * this._intensityBlue);
  }
});